package com.irdstudio.efp.e4a.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.irdstudio.basic.framework.core.constant.BaseConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.DESCoderUtil;
import com.irdstudio.basic.framework.core.util.Des3Utils;
import com.irdstudio.basic.framework.core.util.MD5Util;
import com.irdstudio.basic.framework.core.util.RSAUtils;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TraceUtil;
import com.irdstudio.basic.framework.core.util.URLUtil;
import com.irdstudio.basic.framework.core.vo.DutyInfo;
import com.irdstudio.basic.framework.core.vo.OrgInfo;
import com.irdstudio.basic.framework.core.vo.ResourceCtrl;
import com.irdstudio.basic.framework.core.vo.RoleInfo;
import com.irdstudio.basic.framework.core.vo.UserInfo;
import com.irdstudio.efp.e4a.common.constant.E4AConstant;
import com.irdstudio.efp.e4a.service.dao.E4ADao;
import com.irdstudio.efp.e4a.service.domain.PubSysInfo;
import com.irdstudio.efp.e4a.service.domain.SDuty;
import com.irdstudio.efp.e4a.service.domain.SOrg;
import com.irdstudio.efp.e4a.service.domain.SRole;
import com.irdstudio.efp.e4a.service.domain.SUser;
import com.irdstudio.efp.e4a.service.facade.E4AService;
import com.irdstudio.efp.e4a.service.vo.AuthInfoVO;
import com.irdstudio.efp.e4a.service.vo.SMenuCtrlVO;
import com.irdstudio.efp.e4a.service.vo.SMenuUserVO;
import com.irdstudio.efp.e4a.service.vo.SMenuVO;
import com.irdstudio.efp.esb.service.bo.req.frontsystem.TellerLoginValidationReqBean;
import com.irdstudio.efp.esb.service.bo.req.sed.pls.ReqModifyTellerPassBean;
import com.irdstudio.efp.esb.service.bo.resp.frontsystem.TellerLoginValidationRespBean;
import com.irdstudio.efp.esb.service.facade.frontsystem.TellerLoginValidationService;
import com.irdstudio.efp.esb.service.facade.sed.pls.ModifyTellerPassService;

/**
 * E4A认证服务
 * 
 * @author fuzm
 *
 */
@Service("e4aService")
public class E4AServiceImpl implements E4AService {

	private static final Logger logger = LoggerFactory.getLogger(E4AServiceImpl.class);

	@Autowired
	private E4ADao e4aDao;

	@Autowired
	private StringRedisTemplate template;

	@Autowired
	@Qualifier("tellerLoginValidationService")
	private TellerLoginValidationService tellerLoginValidationService;
	
	@Autowired
	private ModifyTellerPassService modifyTellerPassService;

	@Override
	public AuthInfoVO authToken(AuthInfoVO authInfoVO) {
		AuthInfoVO authInfo = new AuthInfoVO();
		try {
			String rsaPassword = authInfoVO.getPassword();
			// rsaPassword = URLDecoder.decode(rsaPassword, "UTF-8");
			String password = "";
			// RSA解密
			try {
				// password = RSAUtility.decryptByBase64(rsaPassword,
				// E4AConstant.RSA_PRIVATE_KEY);
				password = new String(RSAUtils.decryptByPrivateKey(rsaPassword, E4AConstant.RSA_PRIVATE_KEY));
				authInfoVO.setPassword(password);
			} catch (Exception e) {
				logger.error("RSA解密失败" + e.getMessage(), e);
				throw new Exception("RSA解密是失败" + e.getMessage());
			}

//			 SUser param = new SUser();
//			 param.setUserCode(authInfoVO.getUsercode());
//			 param.setUserPwd(MD5Util.getMD5ofStr(authInfoVO.getUsercode() + password));
//			 SUser user = e4aDao.queryByCodeAndPw(param);

			// 查询是否柜员
			SUser param = new SUser();
			param.setUserCode(authInfoVO.getUsercode());
			param = e4aDao.queryByCode(param);
			SUser user = null;
			if (param != null) {
				// 判断是否柜员
				String isTeller = param.getIsTeller();
				if (BaseConstant.YES_Y.equals(isTeller)) {
					TellerLoginValidationReqBean tellerLoginValidationReqBean = new TellerLoginValidationReqBean();
					tellerLoginValidationReqBean.setSysId("idea");
					tellerLoginValidationReqBean.setTlrCd(authInfoVO.getUsercode());
					tellerLoginValidationReqBean.setTxnCd("CG1007");
					String psw = Des3Utils.encryption("209DD68C90A2E89062908F0903821323", authInfoVO.getPassword());
					if (psw.length() >= 16) {
						psw = psw.substring(0, 16);
					}
					//
					tellerLoginValidationReqBean.setTlrLogonPswd(psw);
					TellerLoginValidationRespBean loginValidate = tellerLoginValidationService.loginValidate(tellerLoginValidationReqBean);
					String tlrAtchOrgNo = loginValidate.getTlrAtchOrgNo();
					user = new SUser();
					user.setUserCode(authInfoVO.getUsercode());
					

				} else {
					param.setUserCode(authInfoVO.getUsercode());
					param.setUserPwd(MD5Util.getMD5ofStr(authInfoVO.getUsercode() + password));
					user = e4aDao.queryByCodeAndPw(param);
				}
			}

			// 校验密码成功
			if (user != null && StringUtil.isNotEmpty(user.getUserCode())) {
				logger.debug("登录成功！");
				long timestamp = System.currentTimeMillis();
				// session中的用户信息初始化
				UserInfo userInfo = new UserInfo();
				userInfo.setUserId(user.getUserCode());
				userInfo.setUserName(user.getUserName());

				// 生成token及验证信息
				String jsonStr = JSONObject.toJSONString(userInfo);
				String token = DESCoderUtil.encrypt(jsonStr);
				String md5 = MD5Util
						.getMD5ofStr(URLUtil.md5(token, Long.valueOf(timestamp), E4AConstant.SECURITY_SALT));

				// 查询法人机构信息
				SOrg legalOrgInfo = e4aDao.queryOrgByLegalOrgCode(user.getLegalOrgCode());
				if (legalOrgInfo != null) {
					OrgInfo legalOrg = new OrgInfo();
					legalOrg.setOrgCode(legalOrgInfo.getOrgCode());
					legalOrg.setOrgName(legalOrgInfo.getOrgName());
					legalOrg.setOrgLocation(legalOrgInfo.getLocation());
					legalOrg.setOrgAreaCode(legalOrgInfo.getAreaCode());
					userInfo.setLegalOrg(legalOrg);
				}

				// 查询机构信息
				SOrg sOrgInfo = e4aDao.queryOrgByUserCode(user.getUserCode());
				if (sOrgInfo != null) {
					OrgInfo orgInfo = new OrgInfo();
					orgInfo.setOrgCode(sOrgInfo.getOrgCode());
					orgInfo.setOrgName(sOrgInfo.getOrgName());
					orgInfo.setOrgLocation(sOrgInfo.getLocation());
					orgInfo.setOrgAreaCode(sOrgInfo.getAreaCode());
					userInfo.setOrgInfo(orgInfo);
				}

				// 查询岗位信息
				List<SDuty> sDutyList = e4aDao.queryDutyByUserCode(user.getUserCode());
				if (sDutyList != null && sDutyList.size() > 0) {
					List<DutyInfo> dutyList = new ArrayList<DutyInfo>();
					for (int i = 0; i < sDutyList.size(); i++) {
						SDuty duty = sDutyList.get(i);
						// 封装duty信息
						DutyInfo dutyInfo = new DutyInfo();
						dutyInfo.setDutyCode(duty.getDutyCode());
						dutyInfo.setDutyName(duty.getDutyName());
						dutyList.add(dutyInfo);
					}
					// 设置岗位信息
					userInfo.setUserDutys(dutyList);
				}

				// 查询角色信息
				List<SRole> sRoleList = e4aDao.queryRoleByUserCode(user.getUserCode());
				if (sRoleList != null && sRoleList.size() > 0) {
					List<RoleInfo> roleList = new ArrayList<RoleInfo>();
					for (int i = 0; i < sRoleList.size(); i++) {
						SRole role = sRoleList.get(i);
						// 封装角色信息
						RoleInfo roleInfo = new RoleInfo();
						roleInfo.setRoleCode(role.getRoleCode());
						roleInfo.setRoleName(role.getRoleName());
						// 设置角色信息
						roleList.add(roleInfo);
					}
					// 设置岗位信息
					userInfo.setUserRoles(roleList);
				}

				// 查询用户菜单权限
				List<ResourceCtrl> rescCtrls = new ArrayList<ResourceCtrl>();
				List<SMenuVO> menuList = e4aDao.queryUserRescData(user.getUserCode());
				List<SMenuCtrlVO> ctrlList = e4aDao.queryUserRescActData(user.getUserCode());
				if (menuList != null && ctrlList != null) {
					for (int i = 0; i < menuList.size(); i++) {
						SMenuVO menuVO = menuList.get(i);
						for (int j = 0; j < ctrlList.size(); j++) {
							SMenuCtrlVO ctrlVO = ctrlList.get(j);

							if (menuVO.getMenuId().equals(ctrlVO.getMenuId())) {
								ResourceCtrl rc = new ResourceCtrl();
								rc.setRescCode(menuVO.getMenuId());
								rc.setRescDesc(menuVO.getMenuName());
								rc.setLegalOrgCode(menuVO.getLegalOrgCode());
								rc.setFuncId(menuVO.getFuncId());
								rc.setRescUrl(menuVO.getFuncUrl());
								rc.setRescParentCode(menuVO.getUpMenuId());
								rc.setRescActCode(ctrlVO.getCtrlCode());
								rc.setRescActDesc(ctrlVO.getCtrlName());
								rescCtrls.add(rc);
							}
						}
					}
					// 设置角色权限
					userInfo.setMenuCtrls(rescCtrls);
				}

				// 设置营业日期
				PubSysInfo sysInfo = e4aDao.queryPubSystInfo();
				if (sysInfo != null) {
					userInfo.setOpenday(sysInfo.getOpenday());
				}

				// 登录用户信息存入redis
				template.delete(E4AConstant.USER_SESSION_KEY_CATCHE + authInfoVO.getSessionId());
				template.opsForValue().set(E4AConstant.USER_SESSION_KEY_CATCHE + authInfoVO.getSessionId(),
						JSONObject.toJSONString(userInfo), E4AConstant.TOKEN_TIMEOUT, TimeUnit.SECONDS);
				// redisService.delete(E4AConstant.USER_SESSION_KEY_CATCHE +
				// authInfoVO.getSessionId());
				// redisService.setex(E4AConstant.USER_SESSION_KEY_CATCHE +
				// authInfoVO.getSessionId(),
				// E4AConstant.TOKEN_TIMEOUT, userInfo);

				authInfo.setUsercode(authInfoVO.getUsercode());
				authInfo.setToken(token);
				authInfo.setSessionId(authInfoVO.getSessionId());
				authInfo.setTimestamp(timestamp);
				authInfo.setMd5(md5);
				authInfo.setUserInfo(userInfo);
			}

		} catch (Exception e) {
			// e.printStackTrace();
			logger.error("获取token失败，错误信息：" + e.getMessage());
		}
		return authInfo;
	}

	@Override
	public AuthInfoVO valifyToken(AuthInfoVO authInfoVO) {
		AuthInfoVO authInfo = null;
		try {
			String token = authInfoVO.getToken();
			String sessionId = authInfoVO.getSessionId();
			String md5 = authInfoVO.getMd5();
			Long timestamp = authInfoVO.getTimestamp();

			authInfo = new AuthInfoVO();
			// 校验token
			if (StringUtils.isNotEmpty(token) && timestamp != null && (StringUtils.isNotEmpty(md5))) {
				try {
					String currentMd5 = MD5Util
							.getMD5ofStr((URLUtil.md5(token, Long.valueOf(timestamp), E4AConstant.SECURITY_SALT)));
					if (!md5.equals(currentMd5)) {
						logger.error("md5校验失败 ，需校验md5为：" + md5 + ",目标md5为：" + currentMd5);
						throw new BizException("md5 not invalid");
					}

					long currenttimemillis = System.currentTimeMillis();
					long timeOut = currenttimemillis - Long.valueOf(timestamp).longValue();
					if (timeOut <= E4AConstant.TtimestampTimeOut.longValue()) {
						String tokenJson = DESCoderUtil.decrypt(token);
						UserInfo userInfo = JSONObject.parseObject(tokenJson, UserInfo.class);
						if ((userInfo == null) || (userInfo.getUserId() == null)) {
							throw new BizException("decode token error.");
						}

						// 更新redis信息
						// redisService.delete(E4AConstant.USER_SESSION_KEY_CATCHE +
						// authInfoVO.getSessionId());
						// redisService.setex(E4AConstant.USER_SESSION_KEY_CATCHE +
						// authInfoVO.getSessionId(), E4AConstant.TOKEN_TIMEOUT, userInfo);
						// redisService.expire(E4AConstant.USER_SESSION_KEY_CATCHE +
						// authInfoVO.getSessionId(), E4AConstant.TOKEN_TIMEOUT);
						template.expire(E4AConstant.USER_SESSION_KEY_CATCHE + authInfoVO.getSessionId(),
								E4AConstant.TOKEN_TIMEOUT, TimeUnit.SECONDS);
					}
				} catch (Exception e) {
					// e.printStackTrace();
					// logger.error("token校验出错,错误信息：" + e.getMessage());
					// authInfo.setCheckToken(false);
					// return authInfo;
					throw new Exception("token校验出错,错误信息：" + e.getMessage());
				}
			}

			// 校验redis中session过期
			// UserInfo userInfo = (UserInfo)
			// this.redisService.get(E4AConstant.USER_SESSION_KEY_CATCHE + sessionId,
			// UserInfo.class);
			UserInfo userInfo = JSONObject.parseObject(
					template.opsForValue().get(E4AConstant.USER_SESSION_KEY_CATCHE + sessionId), UserInfo.class);
			if (userInfo != null && userInfo.getUserId() != null) {
				// logger.info("user info: " + userInfo + ", "
				// + "user id: " + userInfo.getUserId()
				// + ", user name :" + userInfo.getUserName()
				// + ", org name: " + userInfo.getOrgInfo().getOrgName());
				authInfo.setCheckToken(true);
				authInfo.setUserInfo(userInfo);
			} else {
				// logger.error("session信息过期，无法获取登录用户信息校验出错");
				throw new Exception("session信息过期，无法获取登录用户信息校验出错:" + sessionId);
			}

		} catch (Exception e) {
			e.printStackTrace();
			logger.error("验证过程出错，错误信息为：" + e.getMessage());
			authInfo = new AuthInfoVO();
			authInfo.setCheckToken(false);
		}

		return authInfo;
	}

	@Override
	public boolean logout(AuthInfoVO authInfoVO) {
		boolean success = false;
		try {
			String sessionId = authInfoVO.getSessionId();
			if (sessionId != null && StringUtils.isNotEmpty(sessionId)) {
				template.delete(E4AConstant.USER_SESSION_KEY_CATCHE + authInfoVO.getSessionId());
				// redisService.delete(E4AConstant.USER_SESSION_KEY_CATCHE +
				// authInfoVO.getSessionId());
			}
			success = true;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return success;
	}

	@Override
	public SMenuUserVO queryUserMenuInfo(String userCode) {
		SMenuUserVO menuUser = new SMenuUserVO();
		List<SMenuVO> consoleMenu = e4aDao.queryUserRescData(userCode);
		List<SMenuCtrlVO> consoleCtrls = e4aDao.queryUserRescActData(userCode);
		menuUser.setCtrls(consoleCtrls);
		menuUser.setMenus(consoleMenu);

		return menuUser;
	}

	@Override
	public AuthInfoVO modifyUserPassword(AuthInfoVO authInfoVO) {
		AuthInfoVO authInfo = new AuthInfoVO();
		try {
			// RSA解密-原密码解密
			String password = authInfoVO.getPassword();
			String decodePassword = "";
			try {
				decodePassword = new String(RSAUtils.decryptByPrivateKey(password, E4AConstant.RSA_PRIVATE_KEY),
						"UTF-8");
			} catch (Exception e) {
				logger.error("RSA解密失败" + e.getMessage(), e);
				throw new Exception(e);
			}

			// RSA解密-新密码解密
			String newPassword = authInfoVO.getNewPassword();
			String decodeNewPassword = "";
			try {
				decodeNewPassword = new String(RSAUtils.decryptByPrivateKey(newPassword, E4AConstant.RSA_PRIVATE_KEY),
						"UTF-8");
			} catch (Exception e) {
				logger.error("RSA解密失败" + e.getMessage(), e);
				throw new Exception(e);
			}

			SUser param = new SUser();
			param.setUserCode(authInfoVO.getUsercode());
			param.setUserPwd(MD5Util.getMD5ofStr(authInfoVO.getUsercode() + decodePassword));
			param = e4aDao.queryByCodeAndPw(param);
//			SUser param = new SUser();
//			param.setUserCode(authInfoVO.getUsercode());
//			param = e4aDao.queryByCodeAndPw(param);
			SUser user =null ;
			if(param!=null) {
				String isTeller = param.getIsTeller();
				if(BaseConstant.YES_Y.equals(isTeller)) {
					ReqModifyTellerPassBean reqModifyTellerPassBean = new ReqModifyTellerPassBean();
					reqModifyTellerPassBean.setSysCode("idea");
					reqModifyTellerPassBean.setLognid(authInfoVO.getUsercode());
					reqModifyTellerPassBean.setUserpw(Des3Utils.encryption("209DD68C90A2E89062908F0903821323", password));
					reqModifyTellerPassBean.setNewpwd(Des3Utils.encryption("209DD68C90A2E89062908F0903821323", newPassword));
					reqModifyTellerPassBean.setCompwd(Des3Utils.encryption("209DD68C90A2E89062908F0903821323", authInfoVO.getPassword()));
					modifyTellerPassService.modifyPass(reqModifyTellerPassBean);
				}else {
					param.setUserCode(authInfoVO.getUsercode());
					param.setUserPwd(MD5Util.getMD5ofStr(authInfoVO.getUsercode() + decodePassword));
					user = e4aDao.queryByCodeAndPw(param);
				}
			}
			if (user != null) {
				SUser changeParam = new SUser();
				changeParam.setUserCode(user.getUserCode());
				changeParam.setUserPwd(MD5Util.getMD5ofStr(authInfoVO.getUsercode() + decodeNewPassword));
				e4aDao.updateUserPassword(changeParam);

				authInfo.setChangeSuccess(true);
				authInfo.setMessage("密码修改成功!");
			} else {
				logger.error("原密码错误！");
				authInfo.setChangeSuccess(false);
				authInfo.setMessage("原密码错误!");
			}
		} catch (Exception e) {
			logger.error("修改密码失败" + e.getMessage(), e);
			authInfo.setChangeSuccess(false);
			authInfo.setMessage("修改密码错误!");
		}

		return authInfo;
	}

	@Override
	public boolean cacheValidateCode(String clientId, String validateCode) {
		// 保存到redis缓存中
		template.opsForValue().set(E4AConstant.VALIDATE_CODE_KEY_CATCHE + clientId, validateCode,
				E4AConstant.VALIDATE_CODE_TIMEOUT, TimeUnit.SECONDS);
		// redisService.setex(E4AConstant.VALIDATE_CODE_KEY_CATCHE + clientId,
		// E4AConstant.VALIDATE_CODE_TIMEOUT, validateCode);
		return true;
	}

	@Override
	public boolean verifyCodeImage(String clientId, String imageCode) {
		String cacheImageCode = template.opsForValue().get(E4AConstant.VALIDATE_CODE_KEY_CATCHE + clientId);
		// String cacheImageCode = redisService.get(E4AConstant.VALIDATE_CODE_KEY_CATCHE
		// + clientId, String.class);
		if (StringUtil.isNotEmpty(cacheImageCode) && StringUtil.isNotEmpty(imageCode)
				&& cacheImageCode.toLowerCase().equals(imageCode.toLowerCase())) {
			return true;
		} else {
			return false;
		}
	}
}
